package com.jxjk.reportwork.util;

import com.google.common.collect.Maps;
import com.jxjk.reportwork.model.ReportConfig;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.cli.*;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Slf4j
@UtilityClass
public class PropertyUtil {

    /**
     * 解析命令行参数
     *
     * @param args
     */
    public static final void parseCommandLine(String[] args) {
        Options options = new Options();
        String workDirParam = "w";
        String charsetParam = "c";
        //参数为-w D:\work\建信金科\202405报工\202408报工
        options.addRequiredOption(workDirParam, "D:\\work\\建信金科\\202405报工\\202408报工", true, "工作目录");
        options.addRequiredOption(charsetParam, "gb2312", true, "字符集");

        CommandLineParser parser = new DefaultParser();
        HelpFormatter formatter = new HelpFormatter();
        CommandLine cmd = null;

        try {
            cmd = parser.parse(options, args);
            String workDir = cmd.getOptionValue(workDirParam);
            String os = StringUtils.lowerCase(System.getProperty("os.name"));


            String fileSeparator = System.getProperty("file.separator");
            log.info("操作系统类型是:{}, fileSeparator:{}", os, fileSeparator);
            if (StringUtils.endsWith(workDir, fileSeparator) == false) {
                workDir = workDir + fileSeparator;
            }


            String charset = cmd.getOptionValue(charsetParam);
            ReportWorkConstant.WORK_DIR = workDir;
            ReportWorkConstant.CHARSET = charset;
            log.info("workDir:{}, charset:{}", workDir, charset);
        } catch (org.apache.commons.cli.ParseException e) {
            log.error("解析命令行参数异常", e);
            formatter.printHelp("xxx\n\n", options);

            System.exit(1);
        }
    }

    /**
     * 读取配置文件的内容
     *
     * @param configFileName
     * @return
     */
    private Map<String, String> readConfigFile(String configFileName) {
        Map<String, String> paramMap = Maps.newConcurrentMap();

        try {
            List<String> lineList = FileUtils.readLines(new File(configFileName), ReportWorkConstant.CHARSET);
            for (String line : lineList) {
                if (StringUtils.isEmpty(line)) {
                    continue;
                }
                if (StringUtils.startsWith(line, "#")) {
                    continue;
                }
                String[] tmpArr = StringUtils.split(line, "=");
                if (tmpArr == null || tmpArr.length != 2) {
                    log.error("配置行有错误:{}", line);
                }
                String key = StringUtils.trim(tmpArr[0]);
                String value = StringUtils.trim(tmpArr[1]);
                if (paramMap.containsKey(key)) {
                    log.warn("配置行的信息已经存在:{}", line);
                } else {
                    paramMap.put(key, value);
                }
            }
        } catch (IOException e) {
            log.error("读取文件失败, 文件名：{}", configFileName, e);
        }
        return paramMap;
    }

    /**
     * 获取配置
     *
     * @return
     */
    public static final ReportConfig loadConfig() {
        ReportConfig reportConfig = new ReportConfig();
        String configFileName = ReportWorkConstant.WORK_DIR + ReportWorkConstant.COFNIG_FILE_NAME;
        log.info("替换后的文件名称, configFileName: {}", configFileName);
        try {
            Map<String, String> paramMap = readConfigFile(configFileName);
            String startDateStr = StringUtils.trim(paramMap.get("startDate"));
            log.info("configFileName:{}, startDateStr:{}", configFileName, startDateStr);
            Date startDate = DateUtils.parseDate(startDateStr, "yyyy.MM.dd");
            reportConfig.setStartDate(startDate);

            String endDateStr = StringUtils.trim(paramMap.get("endDate"));
            Date endDate = DateUtils.parseDate(endDateStr, "yyyy.MM.dd");
            reportConfig.setEndDate(endDate);


            String workDateSpecial = StringUtils.trim(paramMap.get("workDateSpecial"));
            if (StringUtils.isNotEmpty(workDateSpecial)) {
                String[] tmpArr = StringUtils.split(workDateSpecial, ",");
                for (String tmpString : tmpArr) {
                    Date tmpDate = DateUtils.parseDate(tmpString, "yyyy.MM.dd");
                    reportConfig.getWorkDateSpecialList().add(tmpDate);
                }
            }

            String holidayDateSpecial = StringUtils.trim(paramMap.get("holidayDateSpecial"));
            holidayDateSpecial = StringUtils.trim(holidayDateSpecial);
            if (StringUtils.isNotEmpty(holidayDateSpecial)) {
                String[] tmpArr = StringUtils.split(holidayDateSpecial, ",");
                for (String tmpString : tmpArr) {
                    Date tmpDate = DateUtils.parseDate(tmpString, "yyyy.MM.dd");
                    reportConfig.getHolidayDateSpecialList().add(tmpDate);
                }
            }

            log.info("startDateStr:{}, endDateStr:{}, workDateSpecial:{}, holidayDateSpecial:{}",
                    startDateStr, endDateStr, workDateSpecial, holidayDateSpecial);

            String reportPlanFile = StringUtils.trim(paramMap.get(ReportWorkConstant.REPORT_PLAN_FILE));
            reportConfig.setReportPlanFile(reportPlanFile);

            String realReportFile = StringUtils.trim(paramMap.get(ReportWorkConstant.REAL_REPORT_FILE));
            reportConfig.setRealReportFile(realReportFile);

            String businessTripFile = StringUtils.trim(paramMap.get(ReportWorkConstant.BUSINESS_TRIP_FILE));
            reportConfig.setBusinessTripFile(businessTripFile);

            String workMonth = StringUtils.trim(paramMap.get(ReportWorkConstant.WORK_MONTH));
            reportConfig.setWorkMonth(workMonth);


            log.info("reportPlanFile:{}, realReportFile:{}", reportPlanFile, realReportFile);
        } catch (ParseException e) {
            log.info("读取配置文件出错", e);
        }
        return reportConfig;
    }

    /**
     * 得到一段时间范围内的工作日历，比如[2024.7.26, 2024.8.25]日之前的工作日
     *
     * @param reportConfig
     */
    public static void calcWorkDateList(ReportConfig reportConfig) {
        Calendar start = Calendar.getInstance();
        start.setTime(reportConfig.getStartDate());
        Calendar end = Calendar.getInstance();
        end.setTime(reportConfig.getEndDate());
        int dateDiff = DateUtils.dateDiff('d', start, end);
        dateDiff = Math.abs(dateDiff) + 1;
        for (int i = 0; i < dateDiff; i++) {
            Calendar tmpTime = Calendar.getInstance();
            Date tmpDate = DateUtils.addDate(reportConfig.getStartDate(), i);
            tmpTime.setTime(tmpDate);
            int dayOfWeek = tmpTime.get(Calendar.DAY_OF_WEEK); // 获取日期的星期几
            boolean isWeekend = dayOfWeek == Calendar.SATURDAY || dayOfWeek == Calendar.SUNDAY;
//            log.info("是否为周末? date:{}, result:{}", tmpDate, isWeekend);
            //如果不是周末，且不是特定节假日
            if (isWeekend == false) {
                if (isSpecialHoliday(reportConfig, tmpDate) == false) {
                    reportConfig.getWorkDateList().add(tmpDate);
                }
            } else {
                //如果是周末，且是特定工作日
                if (isSpecialWorkday(reportConfig, tmpDate)) {
                    reportConfig.getWorkDateList().add(tmpDate);
                }
            }
        }

    }


    /**
     * 如果是指定的节假日。由于国家调休，一年之中会有一些特定的节假日
     *
     * @param reportConfig
     * @param currentDate
     * @return
     */
    public boolean isSpecialHoliday(ReportConfig reportConfig, Date currentDate) {
        if (currentDate == null) {
            return false;
        }
        for (Date tmpDate : reportConfig.getHolidayDateSpecialList()) {
            if (tmpDate.getTime() == currentDate.getTime()) {
                return true;
            }
        }
        return false;
    }

    /**
     * 如果是指定的工作日。由于国家调休，一年之中会有一些特定的工作日
     *
     * @param reportConfig
     * @param currentDate
     * @return
     */
    public boolean isSpecialWorkday(ReportConfig reportConfig, Date currentDate) {
        if (currentDate == null) {
            return false;
        }
        for (Date tmpDate : reportConfig.getWorkDateSpecialList()) {
            if (tmpDate.getTime() == currentDate.getTime()) {
                return true;
            }
        }
        return false;
    }
}
